package com.xnx3.j2ee.service;

import java.util.List;

import com.xnx3.j2ee.entity.User;

/**
 * sql查询，首先会先读缓存，如果缓存中没有，再从mysql中取，取出来后再加入缓存。
 * @author 管雷鸣
 *
 */
public interface SqlCacheService {

	/**
	 * 根据主键查记录
	 * <p>这里会先从缓存层中找一下这条记录是否在缓存层中有，如果有就不需要经过数据库，直接从缓存层返回了。 如果缓存层没有，才从数据库中查，查出来后存入缓存层，然后将查询的数据返回。</p>
	 * @param entityClass 实体类，如 {@link User}.class
	 * @param id 主键id，object
	 * @return 实体类。如果查询不到记录，返回null
	 */
	public <E> E findById(Class<E> entityClass , Object id);
	
	/**
	 * 根据主键查记录（可设置缓存过期时间）
	 * @param entityClass 实体类，如 {@link User}.class
	 * @param id 主键id，object
	 * @param expiretime 当前key-value的过期时间，单位是秒。超过后，会自动删除调
	 * @return 实体类。如果查询不到记录，返回null
	 */
	public <E> E findById(Class<E> entityClass , Object id, int expiretime);
	
	/**
	 * 删除缓存的记录。这里只是删除缓存的记录而已，并不会影响mysql表的信息。
	 * 可以用来作为更新缓存使用。
	 * 这里删除的缓存，是 {@link #findById(Class, Object)} 中产生的缓存数据
	 * @param entityClass 实体类，如 {@link User}.class
	 * @param id 主键id，object
	 */
	public void deleteCacheById(Class entityClass, Object id);
	
	
	/**
	 * 根据字段名查一条值，取一条记录。
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param propertyName 数据表字段名(Hibernate 语句的字段名，驼峰命名,非数据库的字段名)
	 * @param value 值
	 * @return 实体类 。如果查询不到记录，返回null
	 */
	public <E> E findAloneByProperty(Class<E> entityClass,String propertyName, Object value);
	
	/**
	 * 根据字段名查一条值，取一条记录。（可设置缓存过期时间）
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param propertyName 数据表字段名(Hibernate 语句的字段名，驼峰命名,非数据库的字段名)
	 * @param value 值
	 * @param expiretime 当前key-value的过期时间，单位是秒。超过后，会自动删除调
	 * @return 实体类 。如果查询不到记录，返回null
	 */
	public <E> E findAloneByProperty(Class<E> entityClass,String propertyName, Object value, int expiretime);
	

	/**
	 * 根据字段名查一条值，取一条记录。（可设置缓存过期时间）
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * 3. 如果获取的信息没有，也就是0条，那么不会进行缓存。只有获取到的信息大于0条，也就是有数据时，才会缓存
	 * 4. 强烈建议不要缓存条数超过30条的数据
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param propertyName 数据表字段名(Hibernate 语句的字段名，驼峰命名,非数据库的字段名)
	 * @param value 值
	 * @param expiretime 当前key-value的过期时间，单位是秒。比如设定为2，则超过2秒后，会自动删除调
	 * @return list 。如果查询不到记录，返回 new ArrayList(); ，size 是 0
	 */
	public <E> List<E> findByProperty(Class<E> entityClass,String propertyName, Object value, int expiretime);
	
	/**
	 * 根据字段名查一条值，取一条记录。
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * 3. 如果获取的信息没有，也就是0条，那么不会进行缓存。只有获取到的信息大于0条，也就是有数据时，才会缓存
	 * 4. 强烈建议不要缓存条数超过30条的数据
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param propertyName 数据表字段名(Hibernate 语句的字段名，驼峰命名,非数据库的字段名)
	 * @param value 值
	 * @return list 。如果查询不到记录，返回 new ArrayList(); ，size 是 0
	 */
	public <E> List<E> findByProperty(Class<E> entityClass,String propertyName, Object value);
	
	/**
	 * 删除缓存的记录。这里只是删除缓存的记录而已，并不会影响mysql表的信息。
	 * 可以用来作为更新缓存使用。
	 * 这里删除的缓存，是 {@link #findAloneByProperty(Class, String, Object)} 跟 {@link #findByProperty(Class, String, Object)} 中产生的缓存数据
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param propertyName 数据表字段名(Hibernate 语句的字段名，驼峰命名,非数据库的字段名)
	 * @param value 值
	 */
	public void deleteCacheByProperty(Class entityClass,String propertyName, Object value);
	

	/**
	 * 根据字段名查一条值，取一条记录。
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param where 查询条件，传入如 "userid=1"，或者 "userid=1 AND isdelete=1"
	 * @return 查询出的实体类。如果查询不到记录，返回null
	 */
	public <E> E findBySql(Class<E> entityClass,String where);
	
	/**
	 * 根据字段名查一条值，取一条记录。（可设置缓存过期时间）
	 * 1. value会自动进行sql注入过滤
	 * 2. 会先从缓存中取，如果缓存中没有，再从mysql中取。取出来如果有值，放入缓存
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param where 查询条件，传入如 "userid=1"，或者 "userid=1 AND isdelete=1"
	 * @param expiretime 当前key-value的过期时间，单位是秒。比如设定为2，则超过2秒后，会自动删除调
	 * @return 查询出的实体类。如果查询不到记录，返回null
	 */
	public <E> E findBySql(Class<E> entityClass,String where, int expiretime);
	
	/**
	 * 删除缓存的记录。这里只是删除缓存的记录而已，并不会影响mysql表的信息。
	 * 可以用来作为更新缓存使用。
	 * 这里删除的缓存，是 {@link #findBySql(Class, String)} 中产生的缓存数据
	 * @param entityClass {@link Class} 实体类，如 {@link User}.class
	 * @param where 查询条件，传入如 "userid=1"，或者 "userid=1 AND isdelete=1"
	 */
	public void deleteCacheBySql(Class entityClass,String where);
	
	/**
	 * 通过原生SQL语句查询,返回List实体类
	 * <br/>示例：查询列出 user 用户表中，id大于1的用户列表信息
	 * <br/>这里强烈建议设置过期时间不要太久，比如1分钟，它的目的只是为了缓解数据库压力而已。
	 * <br/><b>注意，这里如果从数据库是查的结果集是空的，也依旧会new 一个空的list缓存，过期时间到了后再会从数据库重新读</b>
	 * <pre>
	 * 		List<User> userList = sqlCacheService.findBySqlQuery("SELECT * FROM user WHERE id > 1", User.class);
	 * <pre>
	 * @param sql 原生SQL查询语句
	 * @param entityClass 转化为什么实体类输出
	 * @param expiretime 当前key-value的过期时间，单位是秒。比如设定为2，则超过2秒后，会自动删除调
	 * @return List 实体类列表，不会存在为null的情况，如果空则 list.size = 0
	 */
	public <E> List<E> findBySqlQuery(String sqlQuery, Class<E> entityClass, int expiretime);
}